package cn.bjxy.shishaolong.ra_room.service;

import cn.bjxy.shishaolong.common.StatusCode;
import cn.bjxy.shishaolong.common.SysConst;
import cn.bjxy.shishaolong.ra_room.entity.*;
import cn.bjxy.shishaolong.ra_room.mapper.*;
import cn.bjxy.shishaolong.request_answer.entity.Request;
import cn.bjxy.shishaolong.request_answer.mapper.RequestMapper;
import cn.bjxy.shishaolong.system.exception.OperatorFailureException;
import cn.bjxy.shishaolong.system.file.entity.File;
import cn.bjxy.shishaolong.system.file.mapper.FileMapper;
import cn.bjxy.shishaolong.system.profession_course.entity.Course;
import cn.bjxy.shishaolong.system.profession_course.entity.Profession;
import cn.bjxy.shishaolong.system.profession_course.entity.ProfessionCourseRelation;
import cn.bjxy.shishaolong.system.profession_course.entity.StudentProfessionRelation;
import cn.bjxy.shishaolong.system.profession_course.mapper.CourseMapper;
import cn.bjxy.shishaolong.system.profession_course.mapper.ProfessionMapper;
import cn.bjxy.shishaolong.system.profession_course.service.ICourseService;
import cn.bjxy.shishaolong.system.profession_course.service.IProfessionCourseRelationService;
import cn.bjxy.shishaolong.system.profession_course.service.IProfessionService;
import cn.bjxy.shishaolong.system.profession_course.service.IStudentProfessionRelationService;
import cn.bjxy.shishaolong.system.user.entity.SysUserInfo;
import cn.bjxy.shishaolong.system.user.mapper.SysUserInfoMapper;
import cn.bjxy.shishaolong.utils.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 老师答疑室 服务实现类
 * </p>
 *
 * @author 时少龙
 * @since 2019-04-13
 */
@Service
public class RaroomServiceImpl extends ServiceImpl<RaroomMapper, Raroom> implements IRaroomService {

    @Autowired
    private IProfessionService professionService;
    @Autowired
    private IProfessionCourseRelationService proCourseRelateService;
    @Autowired
    private ICourseService courseService;
    @Autowired
    private IStudentProfessionRelationService stuProRelateservice;

    /*=========  答疑室相关的  =========*/
    @Autowired
    private RaroomMapper raroomMapper;
    @Autowired
    private RaroomProfessionRalationMapper professionRalationMapper;
    @Autowired
    private RaroomCourseRalationMapper courseRalationMapper;
    @Autowired
    private RaroomStudentRalationMapper studentRalationMapper;
    @Autowired
    private RaroomFileRalationMapper fileRalationMapper;
    @Autowired
    private RaroomRequestRalationMapper requestRalationMapper;

    //  =============  查询答疑室信息  ================
    @Autowired
    private ProfessionMapper professionMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private SysUserInfoMapper userInfoMapper;
    @Autowired
    private RequestMapper requestMapper;

    @Override
    public IPage<Raroom> queryByCondition(IPage<Raroom> page, Raroom raroom) {
        List<Raroom> list = raroomMapper.queryByCondition(page, raroom);
        setDataForQueryRoom(list);
        return page.setRecords(list);
    }

    @Override
    public List<Raroom> queryByCondition(Raroom raroom) {
        List<Raroom> list = raroomMapper.queryByCondition(raroom);
        setDataForQueryRoom(list);
        return list;
    }

    private void setDataForQueryRoom(List<Raroom> raroomList) {
        if (raroomList != null && raroomList.size() > 0) {
            for (Raroom raroom : raroomList) {

                Integer roomId = raroom.getTid();
                RaroomQueryEntity allEntiy = new RaroomQueryEntity();

                //1.设置专业
                List<Profession> professionList = professionMapper.queryForRoomByRoomId(roomId);
                ArrayList<Integer> proIds = new ArrayList<>();
                if (professionList != null && professionList.size() > 0) { // 存专业id
                    for (Profession pro : professionList) {
                        proIds.add(pro.getTid());
                    }
                    raroom.setProfessionIds(proIds);
                }
                allEntiy.setProfessionList(professionList);

                // TOdo 单独查询
                //2.设置学生
                List<SysUserInfo> studentList = userInfoMapper.queryForRoomByCondition(new SysUserInfo().setRoomId(roomId));
                allEntiy.setStudentList(studentList);
                if (studentList != null && studentList.size() > 0) {
                    ArrayList<Integer> stuIds = new ArrayList<>();
                    for (SysUserInfo stu : studentList) {
                        stuIds.add(stu.getTid());
                    }
                    raroom.setStudentIds(stuIds);
                }

                //3.设置课程
                List<Course> courseList = courseMapper.queryForRoomByRoomId(roomId);
                allEntiy.setCourseList(courseList);
                if (courseList != null && courseList.size() > 0) {
                    ArrayList<Integer> courseIds = new ArrayList<>();
                    for (Course course : courseList) {
                        courseIds.add(course.getTid());
                    }
                    raroom.setCourseIds(courseIds);
                }

                raroom.setAllData(allEntiy);
            }
        }
    }

    @Override
    public RaroomQueryEntity getAllData() {
        // 获取数据
        List<Profession> professionList = professionService.queryByCondition(null);
        List<Course> courseList = courseService.queryByCondition(null);
        List<ProfessionCourseRelation> proCourseRelationList = proCourseRelateService.list();
        List<SysUserInfo> studentList = userInfoMapper.queryAllStudent();
        List<StudentProfessionRelation> stuProRelationList = stuProRelateservice.list(new QueryWrapper<StudentProfessionRelation>().lambda()
                .isNull(StudentProfessionRelation::getDeletedAt));
        // 封装数据
        RaroomQueryEntity raroomQueryEntity = new RaroomQueryEntity();
        raroomQueryEntity.setCourseList(courseList);
        raroomQueryEntity.setProfessionList(professionList);
        raroomQueryEntity.setProCourseRalatelist(proCourseRelationList);
        raroomQueryEntity.setStudentList(studentList);
        raroomQueryEntity.setProStudentRelateList(stuProRelationList);

        return raroomQueryEntity;
    }

    private static final String MAP_KEY_ROLE_KEY = "roleKey";
    private static final String MAP_KEY_IS_OWN_ROOM = "isOwnRoom";
    private static final String MAP_KEY_ROOM_LIST = "roomList";
    private static final String MAP_KEY_USER_INFO = "userInfo";
    private static final String MAP_KEY_IS_APPLY = "isApply";

    /*  ===================== 自己答疑室列表 和自己是否属于某个答疑室 =================== */
    @Override
    public Map queryMyRaRoomList(Integer userId) {
        HashMap<String, Object> map = new HashMap<>();
        SysUserInfo userInfo = userInfoMapper.getUserInfoById(userId);
        map.put(MAP_KEY_USER_INFO, userInfo);
        if (SysConst.ROLE_KEY_STUDENT.equals(userInfo.getRoleKey())) {
            // 学生
            map.put(MAP_KEY_ROLE_KEY, SysConst.ROLE_KEY_STUDENT);
            List<RaroomStudentRalation> studentRalationList = studentRalationMapper.selectList(new QueryWrapper<RaroomStudentRalation>().lambda()
                    .eq(RaroomStudentRalation::getStudentId, userId).isNull(RaroomStudentRalation::getDeletedAt)
                    .eq(RaroomStudentRalation::getStatus, SysConst.RA_ROOM_STUDENT_STATUS_OK));
            if (studentRalationList != null && studentRalationList.size() > 0) {
                ArrayList<Integer> roomIds = new ArrayList<>();  // 存放答疑室id的集合
                studentRalationList.stream().forEach(relate -> {
                    roomIds.add(relate.getRoomId());
                });
                if (roomIds.size() > 0) {
                    List<Raroom> rarooms = raroomMapper.queryByCondition(
                            new Raroom().setIsAdmin(SysConst.RA_ROOM_IS_NOT_ADMIN).setRoomIds(roomIds));
                    if (rarooms != null && rarooms.size() > 0) {
                        map.put(MAP_KEY_ROOM_LIST, rarooms);
                    }
                }
            }
        } else if (SysConst.ROLE_KEY_TEACHER.equals(userInfo.getRoleKey())) { //老师
            map.put(MAP_KEY_ROLE_KEY, SysConst.ROLE_KEY_TEACHER);
            List<Raroom> raroomList = raroomMapper.queryByCondition(
                    new Raroom().setIsAdmin(SysConst.RA_ROOM_IS_NOT_ADMIN).setTeacherId(userId));
            if (raroomList != null && raroomList.size() > 0) {
                map.put(MAP_KEY_ROOM_LIST, raroomList);
            }
        } else {
            map.put(MAP_KEY_ROLE_KEY, SysConst.ROLE_KEY_ADMIN);
        }
        return map;
    }

    @Override
    public Map queryRoomOwn(Integer userId, Integer roomId) {
        Map map = this.queryMyRaRoomList(userId);
        String roleKey = (String) map.get(MAP_KEY_ROLE_KEY);
        List<Raroom> raroomList = (List<Raroom>) map.get(MAP_KEY_ROOM_LIST);
        if (SysConst.ROLE_KEY_TEACHER.equals(roleKey) && raroomList != null && raroomList.size() > 0) { // 老师
            boolean flag = isOwnRoom(roomId, raroomList);
            map.put(MAP_KEY_IS_OWN_ROOM, flag);
        } else if (SysConst.ROLE_KEY_STUDENT.equals(roleKey) && raroomList != null && raroomList.size() > 0) { // 学生
            // 确定是否申请过
            List<RaroomStudentRalation> studentRalationList = studentRalationMapper.selectList(new QueryWrapper<RaroomStudentRalation>().lambda()
                    .eq(RaroomStudentRalation::getStudentId, userId).isNull(RaroomStudentRalation::getDeletedAt)
                    .eq(RaroomStudentRalation::getStatus, SysConst.RA_ROOM_STUDENT_STATUS_NOTHANDLE));
            map.put(MAP_KEY_IS_APPLY, (studentRalationList != null && studentRalationList.size() > 0));

            boolean flag = isOwnRoom(roomId, raroomList);
            map.put(MAP_KEY_IS_OWN_ROOM, flag);
        } else {
            map.put(MAP_KEY_IS_OWN_ROOM, false);
        }
        return map;
    }

    /**
     * 判断答疑室id 是否在答疑室列表中
     *
     * @param roomId
     * @param raroomList
     * @return
     */
    private boolean isOwnRoom(Integer roomId, List<Raroom> raroomList) {
        boolean flag = false;
        for (Raroom raroom : raroomList) {
            if (roomId == raroom.getTid()) flag = true;
        }
        return flag;
    }
    /*  ===================== 自己答疑室列表 和自己是否属于某个答疑室 end=================== */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void open(Raroom raroom) {
        try {
            // 1.插入答疑室的信息
            raroom.getTeacherId();
            Raroom myRoomEntity = new Raroom();
            myRoomEntity.setTeacherId(raroom.getTeacherId()).setDesc(raroom.getDesc());
            if (raroom.getTid() == null) { //新增
                raroomMapper.insert(myRoomEntity);
                saveRoomInfo(raroom, myRoomEntity);
            } else {  // 修改答疑室信息
                //1.修改答疑室表
                raroomMapper.update(myRoomEntity, new UpdateWrapper<Raroom>().lambda().eq(Raroom::getTid, raroom.getTid()));
                //2. 先删除原来的  答疑室关联的专业、课程、学生
                professionRalationMapper.update(new RaroomProfessionRalation().setDeletedAt(LocalDateTime.now()),
                        new UpdateWrapper<RaroomProfessionRalation>()
                                .lambda().eq(RaroomProfessionRalation::getRoomId, raroom.getTid()));
                courseRalationMapper.update(new RaroomCourseRalation().setDeletedAt(LocalDateTime.now()),
                        new UpdateWrapper<RaroomCourseRalation>().lambda()
                                .eq(RaroomCourseRalation::getRoomId, raroom.getTid()));
                studentRalationMapper.update(new RaroomStudentRalation().setDeletedAt(LocalDateTime.now()),
                        new UpdateWrapper<RaroomStudentRalation>().lambda()
                                .eq(RaroomStudentRalation::getRoomId, raroom.getTid()));
                // 2.新增修改的
                myRoomEntity.setTid(raroom.getTid()); // 设置roomId值
                saveRoomInfo(raroom, myRoomEntity);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new OperatorFailureException(StatusCode.OPERATOR_FAILURE, StatusCode.OPERATOR_FAILURE_MSG);
        }
    }

    /**
     * 保存 答疑室 信息  开通和修改答疑室共用
     *
     * @param raroom
     * @param myRoomEntity
     */
    private void saveRoomInfo(Raroom raroom, Raroom myRoomEntity) {
        // 2.插入答疑室和专业的关系数据
        List<Integer> professionIds = raroom.getProfessionIds();
        if (professionIds != null && professionIds.size() > 0) {
            for (Integer professionId : professionIds) {
                RaroomProfessionRalation professionRalation = new RaroomProfessionRalation();
                professionRalation.setRoomId(myRoomEntity.getTid());
                professionRalation.setProfessionId(professionId);
                professionRalationMapper.insert(professionRalation);
            }
        }

        //3. 插入答疑室和课程的关联关系
        List<Integer> courseIds = raroom.getCourseIds();
        if (courseIds != null && courseIds.size() > 0) {
            for (Integer courseId : courseIds) {
                RaroomCourseRalation courseRalation = new RaroomCourseRalation();
                courseRalation.setRoomId(myRoomEntity.getTid()).setCourseId(courseId);
                courseRalationMapper.insert(courseRalation);
            }
        }

        //4. 插入答疑室和学生的管理关系
        List<Integer> studentIds = raroom.getStudentIds();
        if (studentIds != null && studentIds.size() > 0) {
            for (Integer studentId : studentIds) {
                RaroomStudentRalation studentRalation = new RaroomStudentRalation();
                studentRalation.setRoomId(myRoomEntity.getTid()).setStudentId(studentId);
                studentRalationMapper.insert(studentRalation);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean remove(String ids) {
        Boolean flag = true;
        for (String id : ids.split(",")) {
            //1. 对答疑室表逻辑删除
            raroomMapper.update(new Raroom().setDeletedAt(LocalDateTime.now()).setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<Raroom>().lambda().eq(Raroom::getTid, id));

            //2. 删除专业关联信息
            professionRalationMapper.update(new RaroomProfessionRalation().setDeletedAt(LocalDateTime.now())
                            .setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<RaroomProfessionRalation>().lambda()
                            .eq(RaroomProfessionRalation::getRoomId, id));

            // 删除与课程关联信息
            courseRalationMapper.update(new RaroomCourseRalation().setDeletedAt(LocalDateTime.now())
                            .setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<RaroomCourseRalation>().lambda()
                            .eq(RaroomCourseRalation::getRoomId, id));


            // 删除与学生关联信息
            studentRalationMapper.update(new RaroomStudentRalation().setDeletedAt(LocalDateTime.now())
                            .setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<RaroomStudentRalation>().lambda()
                            .eq(RaroomStudentRalation::getRoomId, id));

            // 删除与文件关联信息 // 文件需要逻辑删除
            fileRalationMapper.update(new RaroomFileRalation().setDeletedAt(LocalDateTime.now())
                            .setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<RaroomFileRalation>().lambda()
                            .eq(RaroomFileRalation::getRoomId, id));
            List<RaroomFileRalation> fileRalationList = fileRalationMapper.selectList(
                    new QueryWrapper<RaroomFileRalation>().lambda().eq(RaroomFileRalation::getRoomId, id));
            if (fileRalationList != null && fileRalationList.size() > 0) {
                ArrayList<Integer> fileIds = new ArrayList<>();
                fileRalationList.stream().forEach(fileRelate -> {
                    fileIds.add(fileRelate.getFileId());
                });
                fileMapper.update(new File().setDeletedAt(LocalDateTime.now())
                                .setUpdatedAt(LocalDateTime.now()),
                        new UpdateWrapper<File>().lambda().in(File::getTid, fileIds));
            }

            // TODO 答疑室中新增了问题， 所有原有的问题查询sql需要调整  对问题表进行逻辑删除  // 问题需要逻辑删除
            requestRalationMapper.update(new RaroomRequestRalation().setDeletedAt(LocalDateTime.now())
                            .setUpdatedAt(LocalDateTime.now()),
                    new UpdateWrapper<RaroomRequestRalation>().lambda().eq(RaroomRequestRalation::getRoomId, id));
            List<RaroomRequestRalation> requestRalationList = requestRalationMapper.selectList(
                    new QueryWrapper<RaroomRequestRalation>().lambda().eq(RaroomRequestRalation::getRoomId, id));
            if (requestRalationList != null && requestRalationList.size() > 0) {
                ArrayList<Integer> requestIds = new ArrayList<>();
                requestRalationList.stream().forEach(request -> {
                    requestIds.add(request.getTid());
                });
                requestMapper.update(new Request().setDeletedAt(LocalDateTime.now()).setUpdateAt(LocalDateTime.now()),
                        new UpdateWrapper<Request>().lambda().in(Request::getTid, requestIds));
            }
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeRoomStatus(Integer teacherId, Integer roomStatus) {
        raroomMapper.update(new Raroom().setStatus(roomStatus).setUpdatedAt(LocalDateTime.now()),
                new UpdateWrapper<Raroom>().lambda().eq(Raroom::getTeacherId, teacherId));
    }

    /*=============== 文件相关 start =================*/
    @Autowired
    private FileUtil fileUtil;

    @Override
    public List<File> queryFileByCondition(File file) {
        setUrlPrefix(file);
        return fileMapper.queryForRoomByCondition(file);
    }

    @Override
    public IPage<File> queryFileByCondition(IPage<File> page, File file) {
        // 设置文件url前缀
        setUrlPrefix(file);
        List<File> fileList = fileMapper.queryForRoomByCondition(page, file);
        return page.setRecords(fileList);
    }

    private void setUrlPrefix(File file) {
        file.setUrlPrefix(fileUtil.getFastDfsFileHttpUrl());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void fileUpload(RaroomFileRalation fileRalation) {
        List<Integer> fileIds = fileRalation.getFileIds();
        if (fileIds != null && fileIds.size() > 0) {
            fileIds.stream().forEach(fileId -> {
                RaroomFileRalation tempFileRelate = new RaroomFileRalation().setFileId(fileId).setRoomId(fileRalation.getRoomId());
                fileRalationMapper.insert(tempFileRelate);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(RaroomFileRalation fileRalation) {
        // 删除答疑室 和文件的关联数据
        fileRalationMapper.update(new RaroomFileRalation().setDeletedAt(LocalDateTime.now())
                , new UpdateWrapper<RaroomFileRalation>().lambda()
                        .eq(RaroomFileRalation::getFileId, fileRalation.getFileId())
                        .eq(RaroomFileRalation::getRoomId, fileRalation.getRoomId()));

        // 删除文件的数据
        fileMapper.update(new File().setDeletedAt(LocalDateTime.now()), new QueryWrapper<File>().lambda()
                .eq(File::getTid, fileRalation.getFileId()));
    }
    /*=============== 文件相关 end =================*/

    /*=============== 学生相关 start =================*/
    @Override
    public List<SysUserInfo> queryStudentByCondition(SysUserInfo student) {
        List<SysUserInfo> studentList = userInfoMapper.queryForRoomByCondition(student);
        return studentList;
    }

    @Override
    public IPage<SysUserInfo> queryStudentByCondition(IPage<SysUserInfo> page, SysUserInfo student) {
        List<SysUserInfo> studentList = userInfoMapper.queryForRoomByCondition(page, student);
        return page.setRecords(studentList);
    }

    @Override
    @Transactional
    public void verify(RaroomStudentRalation studentRalation) {
        if (SysConst.RA_ROOM_STUDENT_STATUS_NOTHANDLE == studentRalation.getStatus()) {
            this.remove(studentRalation);
        } else { // 审核通过
            studentRalationMapper.update(new RaroomStudentRalation().setStatus(SysConst.RA_ROOM_STUDENT_STATUS_OK),
                    new UpdateWrapper<RaroomStudentRalation>().lambda()
                            .eq(RaroomStudentRalation::getRoomId, studentRalation.getRoomId())
                            .eq(RaroomStudentRalation::getStudentId, studentRalation.getStudentId()));
        }
    }

    @Override
    public void remove(RaroomStudentRalation studentRalation) {
        studentRalationMapper.update(new RaroomStudentRalation().setDeletedAt(LocalDateTime.now()),
                new UpdateWrapper<RaroomStudentRalation>().lambda()
                        .eq(RaroomStudentRalation::getStudentId, studentRalation.getStudentId())
                        .eq(RaroomStudentRalation::getRoomId, studentRalation.getRoomId()));
    }
    /*=============== 学生相关 end =================*/
}
